Dosen : Prof. Dr. Suhartono M.Kom
instansi : UIN Maliki Malang
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("EBImage")## Bioconductor version 3.12 (BiocManager 1.30.10), R 4.0.3 (2020-10-10)
## Installing package(s) 'EBImage'
## package 'EBImage' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'EBImage'
## Warning in file.copy(savedcopy, lib, recursive = TRUE):
## problem copying C:\Users\bambang\OneDrive\Dokumen\R\win-
## library\4.0\00LOCK\EBImage\libs\x64\EBImage.dll to C:
## \Users\bambang\OneDrive\Dokumen\R\win-library\4.0\EBImage\libs\x64\EBImage.dll:
## Permission denied
## Warning: restored 'EBImage'
##
## The downloaded binary packages are in
## C:\Users\bambang\AppData\Local\Temp\RtmpspUG5V\downloaded_packages
## Installation path not writeable, unable to update packages: boot, class,
## cluster, codetools, foreign, KernSmooth, MASS, Matrix, mgcv, nlme, nnet,
## spatial, survival
## Old packages: 'RCurl', 'tiff', 'xfun'
library(EBImage)# install.packages("jpeg")
library(jpeg)EBImage menggunakan kelas khusus paket Imageuntuk menyimpan dan memproses gambar. Ini memperluas kelas dasar R array, dan semua fungsi paket R (“EBImage”) juga bisa dipanggil langsung pada matriks dan array. Anda dapat mengetahui lebih lanjut tentang kelas ini dengan mengetik ?Image. Mari kita intip ke dalam struktur internal suatu Imageobjek.
str(img)## Formal class 'Image' [package "EBImage"] with 2 slots
## ..@ .Data : num [1:768, 1:512] 0.447 0.451 0.463 0.455 0.463 ...
## ..@ colormode: int 0
..DataSlot berisi array numerik intensitas pixel. Kita melihat bahwa dalam kasus ini arraynya adalah dua dimensi, dengan 768 kali 512 elemen, dan sesuai dengan lebar dan tinggi piksel gambar. Dimensi ini dapat diakses menggunakan dimfungsi, seperti array biasa.
dim(img)## [1] 768 512
Data gambar dapat diakses sebagai R biasa arraymenggunakan pengakses imageData.
imageData(img)[1:3, 1:6]## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 0.4470588 0.4627451 0.4784314 0.4980392 0.5137255 0.5294118
## [2,] 0.4509804 0.4627451 0.4784314 0.4823529 0.5058824 0.5215686
## [3,] 0.4627451 0.4666667 0.4823529 0.4980392 0.5137255 0.5137255
The as.array()metode dapat digunakan untuk memaksa sebuah Imageke array.
is.Image( as.array(img) )## [1] FALSE
Distribusi intensitas piksel dapat diplot dalam histogram, dan jangkauannya diperiksa menggunakan rangefungsi tersebut.
hist(img)range(img)## [1] 0 1
Ringkasan Imageobjek yang berguna juga disediakan oleh showmetode ini, yang dipanggil jika kita hanya mengetikkan nama objek.
img## Image
## colorMode : Grayscale
## storage.mode : double
## dim : 768 512
## frames.total : 1
## frames.render: 1
##
## imageData(object)[1:5,1:6]
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 0.4470588 0.4627451 0.4784314 0.4980392 0.5137255 0.5294118
## [2,] 0.4509804 0.4627451 0.4784314 0.4823529 0.5058824 0.5215686
## [3,] 0.4627451 0.4666667 0.4823529 0.4980392 0.5137255 0.5137255
## [4,] 0.4549020 0.4666667 0.4862745 0.4980392 0.5176471 0.5411765
## [5,] 0.4627451 0.4627451 0.4823529 0.4980392 0.5137255 0.5411765
Untuk representasi yang lebih ringkas tanpa pratinjau larik intensitas, gunakan print method dengan argumen short disetel ke
print( img, short=TRUE)## Image
## colorMode : Grayscale
## storage.mode : double
## dim : 768 512
## frames.total : 1
## frames.render: 1
Gambar berwarna didasarkan pada 3 saluran (RBG).
print(imgcol, short=TRUE)## Image
## colorMode : Color
## storage.mode : double
## dim : 768 512 3
## frames.total : 3
## frames.render: 1
Mereka berbeda dari gambar skala abu-abu berdasarkan properti colorModedan jumlah dimensinya, 3 (B&W) vs. 4 (warna). The colorModeSlot ternyata nyaman ketika berhadapan dengan tumpukan gambar. Jika diatur ke gray-scale, maka dimensi ketiga dan semua yang lebih tinggi dari larik dianggap sebagai bingkai gambar terpisah yang sesuai, misalnya, ke posisi z yang berbeda, titik waktu, ulangan, dll. Di sisi lain, jika colorModeada Color, maka dimensi ketiga diasumsikan memiliki saluran warna yang berbeda, dan hanya dimensi keempat dan lebih tinggi yang digunakan untuk beberapa bingkai gambar. imgcolberisi tiga saluran warna, yang sesuai dengan intensitas merah, hijau, dan biru pada foto. Namun, hal ini tidak harus demikian, dan jumlah saluran warna dapat berubah-ubah.
Bidang “frames.total” dan “frames.render” yang ditampilkan oleh ringkasan objek sesuai dengan jumlah total bingkai yang terdapat dalam gambar, dan dengan jumlah bingkai yang dirender. Angka-angka ini dapat diakses menggunakan fungsi numberOfFramesdengan menentukan typeargumennya.
numberOfFrames(imgcol, type = "render")## [1] 1
numberOfFrames(imgcol, type = "total")## [1] 3
Bingkai gambar dapat diekstraksi menggunakan getFramedan getFrames. getFramemengembalikan bingkai ke-i yang terdapat dalam gambar y. Jika typeadalah “total”, fungsi ini tidak menyadari mode warna dan mengembalikan sebuah-bidang xy. Untuk type=“render”fungsi mengembalikan gambar ke-i seperti yang ditunjukkan oleh fungsi tampilan. Sementara getFramemengembalikan hanya satu bingkai, getFramesmengambil daftar bingkai yang dapat berfungsi sebagai input ke lapplyfungsi -family. Lihat bagian “Thresholding global” untuk ilustrasi dari pendekatan ini.
Mari kita lihat data pencitraan nuklir / seluler, yang berisi total 4 frame yang sesuai dengan 4 gambar skala abu-abu yang terpisah, seperti yang ditunjukkan oleh “frames.render”.
nuc## Image
## colorMode : Grayscale
## storage.mode : double
## dim : 510 510 4
## frames.total : 4
## frames.render: 4
##
## imageData(object)[1:5,1:6,1]
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 0.06274510 0.07450980 0.07058824 0.08235294 0.10588235 0.09803922
## [2,] 0.06274510 0.05882353 0.07843137 0.09019608 0.09019608 0.10588235
## [3,] 0.06666667 0.06666667 0.08235294 0.07843137 0.09411765 0.09411765
## [4,] 0.06666667 0.06666667 0.07058824 0.08627451 0.08627451 0.09803922
## [5,] 0.05882353 0.06666667 0.07058824 0.08235294 0.09411765 0.10588235
Fungsi colorModeini dapat digunakan untuk mengakses dan mengubah properti ini, mengubah mode rendering gambar. Misalnya, jika kita mengambil Colorgambar dan mengubah modenya menjadi gray-scale, maka gambar tidak akan ditampilkan sebagai gambar berwarna lagi, melainkan sebagai tiga bingkai skala abu-abu terpisah yang sesuai dengan saluran merah, hijau, dan biru. Fungsi colorModeini tidak mengubah konten gambar yang sebenarnya tetapi hanya mengubah cara gambar ditampilkan oleh paket R (“EBImage”).
colorMode(imgcol) = Grayscale
display(imgcol, all=TRUE)Konversi ruang warna antara gray-scaledan Colorgambar dilakukan dengan menggunakan fungsi ini channel. Ini memiliki antarmuka yang fleksibel yang memungkinkan untuk mengkonversi salah satu cara antara mode, dan dapat digunakan untuk mengekstrak saluran warna. Tidak seperti colorMode, channelmengubah nilai intensitas piksel gambar.
Colorke gray-scalemode konversi termasuk mengambil rata-rata yang seragam di seluruh saluran RGB, dan mode konversi pelestarian pendaran berbobot yang lebih cocok untuk tujuan tampilan.
The asred, asgreen dan asbluemode mengkonversi gambar skala abu-abu atau array menjadi gambar warna rona tertentu.
Fungsi kenyamanan toRGBmempromosikan gambar skala abu-abu ke ruang warna RGB dengan mereplikasinya di seluruh saluran merah, hijau, dan biru, yang setara dengan panggilan channeldengan mode disetel ke rgb. Saat ditampilkan, gambar ini tidak terlihat berbeda dari skala abu-abunya, yang diharapkan karena informasi antara saluran warna adalah sama. Untuk menggabungkan tiga gambar skala abu-abu menjadi satu gambar rgb, gunakan fungsi tersebut rgbImage.
Fungsi Imageini dapat digunakan untuk membuat gambar berwarna dari vektor karakter atau larik warna R bernama (seperti yang dicantumkan oleh colors()) dan / atau string heksadesimal dalam bentuk “#rrggbb” atau “#rrggbbaa”.
Menjadi array numerik, gambar dapat dengan mudah dimanipulasi oleh salah satu operator aritmatika R. Misalnya, kita dapat menghasilkan gambar negatif hanya dengan mengurangkan gambar dari nilai maksimumnya.
img_neg = max(img) - img
display( img_neg )
Kami juga dapat meningkatkan kecerahan gambar melalui penambahan, menyesuaikan kontras melalui perkalian, dan menerapkan koreksi gamma melalui eksponen.
img_comb = combine(
img,
img + 0.3,
img * 2,
img ^ 0.5
)
display(img_comb, all=TRUE)Dalam contoh di atas, kami telah combinemenggabungkan gambar individual menjadi satu objek gambar multi-bingkai.
Selanjutnya, kami dapat memotong dan membuat ambang gambar dengan operasi matriks standar.
img_crop = img[366:749, 58:441]
img_thresh = img_crop > .5
display(img_thresh)
Operasi thresholding mengembalikan Imageobjek dengan nilai piksel binarisasi. Tipe data R yang digunakan untuk menyimpan gambar seperti itu adalah logical.
img_thresh## Image
## colorMode : Grayscale
## storage.mode : logical
## dim : 384 384
## frames.total : 1
## frames.render: 1
##
## imageData(object)[1:5,1:6]
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] FALSE FALSE FALSE FALSE FALSE FALSE
## [2,] FALSE FALSE FALSE FALSE FALSE FALSE
## [3,] FALSE FALSE FALSE FALSE FALSE FALSE
## [4,] FALSE FALSE FALSE FALSE FALSE FALSE
## [5,] FALSE FALSE FALSE FALSE FALSE FALSE
Untuk transposisi gambar, gunakan transposedaripada fungsi paket R (“basis”) t. Ini karena yang pertama juga berfungsi pada gambar berwarna dan multiframe dengan menukar dimensi spasialnya.
img_t = transpose(img)
display( img_t )Kita hanya melihat satu jenis transformasi spasial, transposisi, tetapi masih banyak lagi, misalnya translasi, rotasi, refleksi, dan penskalaan. translatememindahkan bidang gambar dengan vektor dua dimensi yang ditentukan sedemikian rupa sehingga piksel yang berada di luar wilayah gambar dipotong, dan piksel yang masuk ke wilayah gambar disetel ke latar belakang.
Warna latar belakang dapat disetel menggunakan argumen bg.columum untuk semua fungsi transformasi spasial yang relevan. Default mengatur nilai piksel latar belakang ke nol yang sesuai dengan hitam. Mari kita tunjukkan penggunaan argumen ini rotateyang memutar gambar searah jarum jam dengan sudut yang diberikan.
img_rotate = rotate(img, 30, bg.col = "white")
display(img_rotate)
Untuk menskalakan gambar ke dimensi yang diinginkan, gunakan resize. Jika Anda hanya memberikan salah satu dari lebar atau tinggi, dimensi lainnya secara otomatis dihitung dengan tetap menggunakan rasio aspek asli.
img_resize = resize(img, w=256, h=256)
display(img_resize )
Berfungsi flipdan flopmerefleksikan gambar di sekitar sumbu horizontal dan vertikal, masing-masing.
img_flip = flip(img)
img_flop = flop(img)
display(combine(img_flip, img_flop), all=TRUE)
Transformasi linier spasial diimplementasikan menggunakan affinetransformasi umum . Ini peta koordinat pixel gambar pxmenggunakan matriks transformasi 3x2 mdengan cara berikut: cbind(px, 1) %*% m. Misalnya, pemetaan tipis horizontal dapat diterapkan dengan
m = matrix(c(1, -.5, 128, 0, 1, 0), nrow=3, ncol=2)
img_affine = affine(img, m)
display( img_affine )
Dalam r Biocpkg (“EBImage”), konvolusi 2 dimensi diimplementasikan oleh fungsi filter2, dan fungsi tambahan makeBrushdapat digunakan untuk menghasilkan fungsi bobot. Bahkan, filter2tidak langsung melakukan penjumlahan yang ditunjukkan pada persamaan di atas. Sebaliknya, ia menggunakan Transformasi Fast Fourier dengan cara yang secara matematis setara tetapi secara komputasi lebih efisien.
w = makeBrush(size = 31, shape = 'gaussian', sigma = 5)
plot(w[(nrow(w)+1)/2, ], ylab = "w", xlab = "", cex = 0.7)img_flo = filter2(img, w)
display(img_flo)Di sini kita telah menggunakan filter Gaussian dengan lebar 5 yang diberikan oleh sigma. Bentuk filter lain yang tersedia termasuk “box”(default) “disc”,, “diamond”dan “line”, untuk beberapa di antaranya kernel dapat berupa biner; lihat makeBrush untuk detailnya.
Jika gambar yang difilter berisi beberapa bingkai, filter diterapkan ke setiap bingkai secara terpisah. Untuk kenyamanan, gambar juga dapat dihaluskan menggunakan fungsi pembungkus gbluryang melakukan penghalusan Gaussian dengan ukuran filter yang secara otomatis disesuaikan sigma.
nuc_gblur = gblur(nuc, sigma = 5)
display(nuc_gblur, all=TRUE )
Dalam pemrosesan sinyal, operasi penghalusan gambar disebut sebagai pemfilteran low-pass. High-pass filtering adalah operasi kebalikannya yang memungkinkan untuk mendeteksi tepi dan mempertajam gambar. Ini dapat dilakukan, misalnya, menggunakan filter Laplacian.
fhi = matrix(1, nrow = 3, ncol = 3)
fhi[2, 2] = -8
img_fhi = filter2(img, fhi)
display(img_fhi)Pendekatan lain untuk melakukan pengurangan kebisingan adalah dengan menerapkan filter median, yang merupakan teknik non-linier sebagai lawan dari filter konvolusi lintasan rendah yang dijelaskan di bagian sebelumnya. Pemfilteran median sangat efektif dalam kasus derau spekel, dan memiliki keuntungan menghilangkan derau sekaligus mempertahankan tepian.
Filter median lokal bekerja dengan memindai gambar piksel demi piksel, mengganti setiap piksel dengan median tetangganya di dalam jendela dengan ukuran yang ditentukan. Teknik pemfilteran ini disediakan dalam paket R (“EBImage”) oleh fungsinya medianFilter. Kami mendemonstrasikan penggunaannya dengan terlebih dahulu merusak gambar dengan noise seragam, dan merekonstruksi gambar asli dengan median filtering.
l = length(img)
n = l/10
pixels = sample(l, n)
img_noisy = img
img_noisy[pixels] = runif(n, min=0, max=1)
display(img_noisy)img_median = medianFilter(img_noisy, 1)
display(img_median)
erosi: Untuk setiap piksel latar depan, letakkan topeng di sekitarnya, dan jika ada piksel yang ditutupi oleh topeng berasal dari latar belakang, setel piksel ke latar belakang.
dilation: Untuk setiap piksel latar belakang, letakkan mask di sekitarnya, dan jika ada piksel yang ditutupi oleh mask berasal dari latar depan, setel piksel ke latar depan.
shapes = readImage(system.file('images', 'shapes.png', package='EBImage'))
logo = shapes[110:512,1:130]
display(logo)kern = makeBrush(5, shape='diamond')
display(kern, interpolate=FALSE)logo_erode= erode(logo, kern)
logo_dilate = dilate(logo, kern)
display(combine(logo_erode, logo_dilate), all=TRUE)
Pembukaan dan penutupan adalah kombinasi dari dua operasi di atas: pembukaan melakukan erosi diikuti oleh dilatasi, sedangkan penutupan melakukan sebaliknya, yaitu melakukan dilasi diikuti oleh erosi. Pembukaan berguna untuk menghilangkan derau morfologis, karena menghilangkan objek kecil dari latar belakang, dan menutup dapat digunakan untuk mengisi lubang kecil di latar depan. Operasi ini dilaksanakan oleh openingdan closing.
Ambang batas Otsu dapat dihitung menggunakan fungsi tersebut otsu. Saat dipanggil pada gambar multi-bingkai, ambang dihitung untuk setiap bingkai secara terpisah sehingga menghasilkan vektor keluaran dengan panjang yang sama dengan jumlah total bingkai pada gambar.
threshold = otsu(nuc)
threshold## [1] 0.3535156 0.4082031 0.3808594 0.4121094
nuc_th = combine( mapply(function(frame, th) frame > th, getFrames(nuc), threshold, SIMPLIFY=FALSE) )
display(nuc_th, all=TRUE) Perhatikan penggunaan getFramesuntuk membagi gambar menjadi daftar bingkai individu, dan combineuntuk menggabungkan kembali hasilnya.
Thresholding adaptif bekerja dengan membandingkan intensitas setiap piksel dengan latar belakang yang ditentukan dari lingkungan lokal. Ini dapat dicapai dengan membandingkan gambar dengan versi yang dihaluskan, di mana jendela pemfilteran lebih besar dari ukuran umum objek yang ingin kita tangkap.
disc = makeBrush(31, "disc")
disc = disc / sum(disc)
offset = 0.05
nuc_bg = filter2( nuc, disc )
nuc_th = nuc > nuc_bg + offset
display(nuc_th, all=TRUE)
Teknik ini mengasumsikan bahwa objek tersebar relatif jarang dalam citra, sehingga distribusi sinyal di lingkungan tersebut didominasi oleh latar belakang. Sementara untuk inti dalam gambar kami, asumsi ini masuk akal, untuk situasi lain Anda mungkin perlu membuat asumsi yang berbeda. Tersedia thresholding adaptif menggunakan filter linier dengan kotak persegi panjang thresh, yang menggunakan implementasi yang lebih cepat dibandingkan dengan langsung menggunakan filter2.
display( thresh(nuc, w=15, h=15, offset=0.05), all=TRUE )# FFT SHIFT
#' This function is useful for visualizing the Fourier transform with the zero-frequency
#' component in the middle of the spectrum.
#'
#' @param img_ff A Fourier transform of a 1D signal, 2D image, or 3D volume.
#' @param dim Number of dimensions (-1, 1, 2, 3).
#' @return A properly shifted FT of the array.
#'
fftshift <- function(img_ff, dim = -1) {
rows <- dim(img_ff)[1]
cols <- dim(img_ff)[2]
# planes <- dim(img_ff)[3]
swap_up_down <- function(img_ff) {
rows_half <- ceiling(rows/2)
return(rbind(img_ff[((rows_half+1):rows), (1:cols)], img_ff[(1:rows_half), (1:cols)]))
}
swap_left_right <- function(img_ff) {
cols_half <- ceiling(cols/2)
return(cbind(img_ff[1:rows, ((cols_half+1):cols)], img_ff[1:rows, 1:cols_half]))
}
#swap_side2side <- function(img_ff) {
# planes_half <- ceiling(planes/2)
# return(cbind(img_ff[1:rows, 1:cols, ((planes_half+1):planes)], img_ff[1:rows, 1:cols, 1:planes_half]))
#}
if (dim == -1) {
img_ff <- swap_up_down(img_ff)
return(swap_left_right(img_ff))
}
else if (dim == 1) {
return(swap_up_down(img_ff))
}
else if (dim == 2) {
return(swap_left_right(img_ff))
}
else if (dim == 3) {
# Use the `abind` package to bind along any dimension a pair of multi-dimensional arrays
# install.packages("abind")
library(abind)
planes <- dim(img_ff)[3]
rows_half <- ceiling(rows/2)
cols_half <- ceiling(cols/2)
planes_half <- ceiling(planes/2)
img_ff <- abind(img_ff[((rows_half+1):rows), (1:cols), (1:planes)],
img_ff[(1:rows_half), (1:cols), (1:planes)], along=1)
img_ff <- abind(img_ff[1:rows, ((cols_half+1):cols), (1:planes)],
img_ff[1:rows, 1:cols_half, (1:planes)], along=2)
img_ff <- abind(img_ff[1:rows, 1:cols, ((planes_half+1):planes)],
img_ff[1:rows, 1:cols, 1:planes_half], along=3)
return(img_ff)
}
else {
stop("Invalid dimension parameter")
}
}str(img)## Formal class 'Image' [package "EBImage"] with 2 slots
## ..@ .Data : num [1:768, 1:512] 0.447 0.451 0.463 0.455 0.463 ...
## ..@ colormode: int 0
imgMat <- matrix(img, nrow = dim(img)[1], ncol = dim(img)[2])
dim(imgMat)## [1] 768 512
ft_imgMat <- fft(imgMat) # fftw2d # Display Re(FT):
display(fftshift(ft_imgMat))## Warning in storage.mode(x) <- "double": imaginary parts discarded in coercion
mag_ft_imgMat <- sqrt(Re(ft_imgMat)^2+Im(ft_imgMat)^2)
display(mag_ft_imgMat)# Phase <- atan(Im(img_ff)/Re(img_ff))
phase_ft_imgMat <- atan2(Im(ft_imgMat), Re(ft_imgMat))
# display(phase_ft_imgMat)
# Display FT
EBImage::display(log(fftshift(ft_imgMat)), title="FT Magnitude (Cyrillic Alphabet)")## Warning in storage.mode(x) <- "double": imaginary parts discarded in coercion
# IFT Reconstruction: Magnitude=mag_ft_imgMat AND Phase=phase_ft_imgMat
Real = mag_ft_imgMat * cos(phase_ft_imgMat)
Imaginary = mag_ft_imgMat * sin(phase_ft_imgMat)
ift_ft_imgMat = Re(fft(Real+1i*Imaginary, inverse = T)/length(mag_ft_imgMat))
EBImage::display(ift_ft_imgMat, method = "raster", title="(IFT o FT) Magnitude=Img | Phase=Img")mag_ft_imgMat_1 <- mag_ft_imgMat
for (i in 1:dim(mag_ft_imgMat)[1]) {
for (j in 1:dim(mag_ft_imgMat)[2]) {
if (abs(i-(dim(mag_ft_imgMat)[1])/2) > (dim(mag_ft_imgMat)[1])/4 |
abs(j-(dim(mag_ft_imgMat)[2])/2) > (dim(mag_ft_imgMat)[2])/4) {
mag_ft_imgMat_1[i,j] <- 0
}
}
}
EBImage::display(mag_ft_imgMat_1, method = "raster", title="(IFT o LowPassFilter o FT) Magnitude=Img | Phase=Img")Real = mag_ft_imgMat_1 * cos(phase_ft_imgMat)
Imaginary = mag_ft_imgMat_1 * sin(phase_ft_imgMat)
ift_ft_imgMat_1 = Re(fft(Real+1i*Imaginary, inverse = T)/length(mag_ft_imgMat_1))
EBImage::display(100*ift_ft_imgMat_1, method = "raster", title="(IFT o LowPassFilter o FT) Magnitude=Img | Phase=Img")# High-pass frequency filtering, remove Fourier coeff's indexed below k_{x,max/4} and k_{y,max/4}
mag_ft_imgMat_2 <- mag_ft_imgMat
for (i in 1:dim(mag_ft_imgMat)[1]) {
for (j in 1:dim(mag_ft_imgMat)[2]) {
if (abs(i-(dim(mag_ft_imgMat)[1])/2) < (dim(mag_ft_imgMat)[1])/4 &
abs(j-(dim(mag_ft_imgMat)[2])/2) < (dim(mag_ft_imgMat)[2])/4) {
mag_ft_imgMat_2[i,j] <- 0
}
}
}
EBImage::display(mag_ft_imgMat_2, method = "raster", title="(IFT o HighPassFilter o FT) Magnitude=Img | Phase=Img")Real = mag_ft_imgMat_2 * cos(phase_ft_imgMat)
Imaginary = mag_ft_imgMat_2 * sin(phase_ft_imgMat)
ift_ft_imgMat_2 = Re(fft(Real+1i*Imaginary, inverse = T)/length(mag_ft_imgMat_2))
EBImage::display(ift_ft_imgMat_2, method = "raster", title="(IFT o HighPassFilter o FT) Magnitude=Img | Phase=Img")Segmentasi gambar melakukan partisi gambar, dan biasanya digunakan untuk mengidentifikasi objek dalam gambar. Objek terhubung yang tidak menyentuh dapat disegmentasi menggunakan fungsi tersebut bwlabel, sedangkan watersheddan propagatemenggunakan algoritme yang lebih canggih dapat memisahkan objek yang saling bersentuhan.
bwlabelmenemukan setiap kumpulan piksel yang terhubung selain latar belakang, dan memberi label ulang kumpulan ini dengan bilangan bulat unik yang meningkat. Itu dapat dipanggil pada gambar biner ambang batas untuk mengekstrak objek.
logo_label = bwlabel(logo)
table(logo_label)## logo_label
## 0 1 2 3 4 5 6 7
## 42217 1375 2012 934 1957 1135 1697 1063
Nilai piksel logo_labelrentang gambar dari 0 sesuai dengan latar belakang hingga jumlah objek yang dikandungnya, yang diberikan oleh
max(logo_label)## [1] 7
Untuk menampilkan gambar kita menormalkannya ke kisaran (0,1) yang diharapkan oleh fungsi tampilan. Ini menghasilkan objek berbeda yang dirender dengan bayangan abu-abu yang berbeda.
display( normalize(logo_label) )
Gradien skala abu-abu horizontal yang dapat diamati mencerminkan cara bwlabelmemindai gambar dan memberi label pada set yang terhubung: dari kiri ke kanan dan dari atas ke bawah. Cara lain untuk memvisualisasikan segmentasi adalah dengan menggunakan colorLabelsfungsi, yang memberi kode warna pada objek dengan permutasi acak warna unik.
display( colorLabels(logo_label) )Beberapa nuklei nucberada cukup dekat satu sama lain dan bergabung menjadi satu objek besar saat diberi ambang batas, seperti yang terlihat di nuc_th. bwlabelakan salah mengidentifikasi mereka sebagai satu objek. Transformasi daerah aliran sungai memungkinkan untuk mengatasi masalah ini. The watershedalgoritma memperlakukan citra skala abu-abu sebagai bantuan topografi, atau tinggi-peta. Objek yang menonjol dari latar belakang diidentifikasi dan dipisahkan dengan membanjiri gambar sumber yang terbalik. Dalam kasus gambar biner, peta jaraknya dapat berfungsi sebagai peta ketinggian masukan. Peta jarak, yang berisi untuk setiap piksel jarak ke piksel latar belakang terdekat, dapat diperoleh distmap.
nmask = watershed( distmap(nuc_th), 2 )
display(colorLabels(nmask), all=TRUE)Voronoi tessellation berguna ketika kita memiliki sekumpulan titik benih (atau daerah) dan ingin membagi ruang yang terletak di antara benih-benih ini sedemikian rupa sehingga setiap titik dalam ruang tersebut ditetapkan ke benih terdekatnya. Fungsi ini diimplementasikan dalam paket R (“EBImage”) oleh fungsi tersebut propagate. Mari kita ilustrasikan konsep Voronoi tessellation pada contoh dasar. Kami menggunakan topeng inti nmasksebagai benih dan membagi ruang di antara mereka.
Aplikasi web 2D Interactive Voronoi Tessellation memberikan contoh langsung dari 2D Voronoi tessellation dinamis.
voronoiExamp = propagate(seeds = nmask, x = nmask, lambda = 100)
voronoiPaint = colorLabels (voronoiExamp)
display(voronoiPaint)## Only the first frame of the image stack is displayed.
## To display all frames use 'all = TRUE'.
Paket R (“EBImage”) mendefinisikan topeng objek sebagai sekumpulan piksel dengan nilai integer unik yang sama. Biasanya, gambar yang mengandung masker objek adalah hasil dari fungsi segmentasi seperti bwalabel, watershed, atau propagate. Objek dapat dihapus dari gambar tersebut dengan rmObject, yang menghapus objek dari topeng hanya dengan mengatur nilai pikselnya ke 0. Secara default, setelah penghapusan objek semua objek yang tersisa diberi label ulang sehingga ID objek tertinggi sesuai dengan jumlah objek di topeng. The reenumerateargumen dapat digunakan untuk mengubah perilaku ini dan untuk melestarikan ID objek asli.
objects = list(
seq.int(from = 2, to = max(logo_label), by = 2),
seq.int(from = 1, to = max(logo_label), by = 2)
)
logos = combine(logo_label, logo_label)
z = rmObjects(logos, objects, reenumerate=FALSE)
display(z, all=TRUE)
Dalam contoh di atas, kami mendemonstrasikan bagaimana fungsi penghapusan objek dapat diterapkan ke gambar multi-bingkai dengan memberikan daftar indeks objek yang akan dihapus dari setiap bingkai. Selain itu kami telah mengatur reenumerateuntuk FALSEmenyimpan ID objek asli.
showIds = function(image) lapply(getFrames(image), function(frame) unique(as.vector(frame)))
showIds(z)## [[1]]
## [1] 0 1 3 5 7
##
## [[2]]
## [1] 0 2 4 6
Ingatlah bahwa 0 berarti latar belakang. Jika pada tahap tertentu kita memutuskan untuk melabel ulang objek, kita dapat menggunakan fungsi standalone untuk ini reenumarate
showIds( reenumerate(z) )## [[1]]
## [1] 0 1 2 3 4
##
## [[2]]
## [1] 0 1 2 3
filled_logo = fillHull(logo)
display(filled_logo)
floodFillmengisi wilayah gambar dengan warna tertentu. Pengisian dimulai pada titik tertentu, dan wilayah pengisian diperluas ke area yang terhubung di mana perbedaan mutlak dalam intensitas piksel tetap di bawah tolerance. Spesifikasi warna menggunakan nama warna R untuk Colorgambar, dan nilai numerik untuk gray-scalegambar.
rgblogo = toRGB(logo)
points = rbind(c(50, 50), c(100, 50), c(150, 50))
colors = c("red", "green", "blue")
rgblogo = floodFill(rgblogo, points, colors)
display( rgblogo )display(floodFill(img, rbind(c(200, 300), c(444, 222)), col=0.2, tolerance=0.2))Diberikan gambar yang berisi objek masker, fungsi tersebut paintObjectsdapat digunakan untuk menyorot objek dari topeng dalam gambar target yang disediakan dalam tgtargumen. Objek dapat diberi kerangka dan diisi dengan warna opasitas tertentu yang ditentukan dalam argumen coldan opac, masing-masing. Jika spesifikasi warna hilang atau sama, NAitu tidak dicat.
d1 = dim(img)[1:2]
overlay = Image(dim=d1)
d2 = dim(logo_label)-1
offset = (d1-d2) %/% 2
overlay[offset[1]:(offset[1]+d2[1]), offset[2]:(offset[2]+d2[2])] = logo_label
img_logo = paintObjects(overlay, toRGB(img), col=c("red", "yellow"), opac=c(1, 0.3), thick=TRUE)
display( img_logo )
Pada contoh di atas kita telah membuat mask baru yang overlaycocok dengan ukuran gambar target kita img, dan menyalin mask yang berisi logo “EBImage” ke dalam overlay mask. Output dari paintObjectsmempertahankan mode warna dari gambar targetnya, oleh karena itu untuk memiliki logo yang disorot dalam warna perlu dikonversi imgke gambar RGB terlebih dahulu, jika tidak, hasilnya akan menjadi gambar skala abu-abu. The thickArgumen kontrol objek kontur gambar: jika set ke FALSE, hanya dalam satu-pixel batas objek ditandai; jika disetel ke TRUE, batas luar juga akan disorot sehingga menghasilkan lebar kontur dua piksel yang bertambah.
#Contoh Segmentasi sel Kami menyimpulkan vignette kami dengan menerapkan fungsi yang dijelaskan sebelumnya untuk tugas segmentasi sel. Tujuan kami adalah untuk mengidentifikasi secara komputasi dan mengkarakterisasi secara kualitatif sel dalam sampel gambar mikroskop fluoresen. Meskipun ini dengan sendirinya mungkin tampak sebagai tujuan yang sederhana, pendekatan ini dapat diterapkan pada koleksi yang berisi ribuan gambar, yang tidak perlu lagi menjadi tujuan yang sederhana!
Kami mulai dengan memuat gambar inti dan badan sel. Untuk memvisualisasikan sel, kami melapisi gambar-gambar ini sebagai saluran hijau dan biru dari gambar berwarna palsu.
nuc = readImage(system.file('images', 'nuclei.tif', package='EBImage'))
cel = readImage(system.file('images', 'cells.tif', package='EBImage'))
cells = rgbImage(green=1.5*cel, blue=nuc)
display(cells, all = TRUE)
Pertama, kita segmen inti menggunakan thresh, fillHull, bwlabel dan opening.
nmask = thresh(nuc, w=10, h=10, offset=0.05)
nmask = opening(nmask, makeBrush(5, shape='disc'))
nmask = fillHull(nmask)
nmask = bwlabel(nmask)
display(nmask, all=TRUE)
Selanjutnya, kami menggunakan inti tersegmentasi sebagai benih dalam segmentasi Voronoi dari sitoplasma.
ctmask = opening(cel>0.1, makeBrush(5, shape='disc'))
cmask = propagate(cel, seeds=nmask, mask=ctmask)
display(ctmask, all=TRUE)
Untuk memvisualisasikan segmentasi kita pada yang kita gunakan paintObject.
segmented = paintObjects(cmask, cells, col='#ff00ff')
segmented = paintObjects(nmask, segmented, col='#ffff00')
display(segmented, all=TRUE)